package com.alogic.cert;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;

import com.anysoft.util.BaseException;
import com.anysoft.util.IOTools;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 证书内容
 * 
 * @author yyduan
 *
 * @since 1.6.11.9
 * 
 * @version 1.6.11.55 [20180822 duanyy] <br>
 * - 增加获取证书序列号功能; <br>
 * 
 * @version 1.6.11.56 [20180823 duanyy] <br>
 * - 证书的序列号可定制; <br>
 *
 * @version 1.6.13.40 [20210306 duanyy] <br>
 * - 优化证书框架 <br>
 */
public interface CertificateContent {
	
	/**
	 * 获取证书序列号
	 * @return 序列号
	 */
	public String getCertId();

	public String getX500Name();
	
	/**
	 * 设置内容
	 * @param cert 证书内容
	 * @param key 私钥内容
	 */
	public void setContent(String id, X509Certificate cert, PrivateKey key);

	public X509Certificate getCertificate();

	public PrivateKey getPrivateKey();
	
	/**
	 * 获取私钥内容
	 * 
	 * @param raw 是否已原始格式输出
	 * @return 私钥内容
	 */
	public byte[] getKey(boolean raw);
	
	/**
	 * 获取证书内容
	 * 
	 * @param raw 是否已原始格式输出
	 * @return 证书内容
	 */
	public byte[] getCert(boolean raw);
	
	/**
	 * 保存私钥内容到文件
	 * 
	 * @param filepath
	 */
	public void saveKey(String filepath);
	
	/**
	 * 保存证书内容到文件
	 * 
	 * @param filepath
	 */
	public void saveCert(String filepath);	
	
	/**
	 * 缺省实现
	 * @author yyduan
	 *
	 */
	public class Default implements CertificateContent{
		/**
		 * a logger of slf4j
		 */
		protected static final Logger LOG = LoggerFactory.getLogger(Default.class);

		protected X509Certificate cert;
		protected PrivateKey key;
		protected String id;
		
		@Override
		public void setContent(String id,X509Certificate cert, PrivateKey key) {
			this.cert = cert;
			this.key = key;
			this.id = id;
		}

		@Override
		public X509Certificate getCertificate() {
			return cert;
		}

		@Override
		public PrivateKey getPrivateKey() {
			return key;
		}

		@Override
		public String getX500Name(){
			return cert.getSubjectX500Principal().getName();
		}

		@Override
		public String getCertId(){
			return this.id;
		}
		
		@Override
		public byte[] getKey(boolean raw) {
			return this.key.getEncoded();
		}

		@Override
		public byte[] getCert(boolean raw) {
			try {
				return this.cert.getEncoded();
			} catch (CertificateEncodingException e) {
				LOG.error(ExceptionUtils.getStackTrace(e));
			}
			return null;
		}

		@Override
		public void saveKey(String filepath) {
			saveContent(filepath,getKey(true));
		}

		@Override
		public void saveCert(String filepath) {
			saveContent(filepath,getCert(true));
		}

		protected void saveContent(String filepath,byte[] content){
			if (content != null && content.length > 0) {
				File file = new File(filepath);
				if (file.exists()) {
					throw new BaseException("core.e1016", String.format("File %s exist.", filepath));
				}

				if (file.canWrite()) {
					throw new BaseException("core.e1017", String.format("File %s can not be written.", filepath));
				}

				OutputStream out = null;

				try {
					out = new FileOutputStream(file);
					out.write(content);
					out.flush();
				} catch (Exception e) {
					throw new BaseException("core.e1004", String.format("Failed to write file %s", filepath));
				} finally {
					IOTools.close(out);
				}
			}
		}
		
	}
}
